/*
*    Phantom v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
// PhantomAgentDlg.cpp : implementation file
//

#include "stdafx.h"
#include "PhantomAgent.h"
#include "PhantomAgentDlg.h"
#include "phantomagentdlg.h"
#include "ThreadFunctions.h"
#include "SSI_SocketManager.h"
#include "SSI_socket_stream.h"
#include ".\phantomagentdlg.h"
#include "optionsdlg.h"
#include "Reg.h"
#include "RegistrationSplashDlg.h"

#include <crtdbg.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define ID_TIMER			20010
#define TIMER_DELTA			250
//#define TIMER_DELTA			10000

#define IDC_TOOLBAR		  20000

#define TRAY_CALLBACK		20001
#define ID_TRAY_VIEW		20011


DWORD WINAPI ListenThreadFunction(void* Param);
DWORD WINAPI ConnectionThreadFunction(void* Param);




// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CPhantomAgentDlg dialog



CPhantomAgentDlg::CPhantomAgentDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPhantomAgentDlg::IDD, pParent)
	, ConnectionList(NULL)
	, TimerHandle(0)
	, m_RecvCnt(0)
	, m_SentCnt(0)
	, m_HiddenFlg(FALSE)
  , bRegistered(FALSE)
{
	//m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON2);
  m_FirstTimer = TRUE;
}

void CPhantomAgentDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CPhantomAgentDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_TIMER()
	ON_COMMAND(ID_VIEW_OPTIONS, OnViewOptions)
	ON_COMMAND(ID_VIEW_HIDE, OnViewHide)
	ON_COMMAND(ID_VIEW_EXIT, OnViewExit)
	ON_MESSAGE(TRAY_CALLBACK, OnTrayNotify)
	ON_COMMAND(ID_TRAY_VIEW, OnPopupShow)
END_MESSAGE_MAP()


// CPhantomAgentDlg message handlers

BOOL CPhantomAgentDlg::OnInitDialog()
{
	//_CrtSetBreakAlloc(6713);
	//_CrtSetBreakAlloc(212746);
	//_CrtSetBreakAlloc(6110);
	//_CrtSetBreakAlloc(6012);
	//_CrtSetBreakAlloc(5461);
	//_CrtSetBreakAlloc(2772);
	//_CrtSetBreakAlloc(241);


	// OK, when a force-kill, delete the engine/interpreter

  

	CDialog::OnInitDialog();

	if(!options.LoadFromFile(OPTIONS_FILE)){
		DispErrorBox("Error loading options file (.\\agent_options.dat)");
	}


	ValidateOptions();
	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

  InitLogFile();

	DWORD tID;
	HANDLE hListener = CreateThread(NULL, 0, ListenThreadFunction, (LPVOID)this, 0, &tID);

	TimerHandle = (UINT)SetTimer(ID_TIMER, TIMER_DELTA, NULL);
	
	InitControls();
  
  

	CSocketSSI::Init();
	char Buff[1024];
	CSocketSSI::GetHostName(Buff, 1024);
	String sName = Buff;
	SetDlgItemText(IDC_MACHINE_NAME, sName.Str());
	CSocketSSI::CleanUp();
	UpdateDataDisplay();
	SetIconic();

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CPhantomAgentDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CPhantomAgentDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPhantomAgentDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


int CPhantomAgentDlg::AddConnection(const char* inHost, const char* inPort)
{

	LVITEM* Insert = new LVITEM;

	int itemCount = ConnectionList->GetItemCount();
	int Index;

	Insert->mask = LVIF_TEXT;
	Insert->iSubItem = 0;
	Insert->iItem = itemCount;
	Insert->pszText = (LPSTR)inHost;
	Insert->cchTextMax = (int)strlen(inHost);
	Index = ConnectionList->InsertItem(Insert);

	Insert->iSubItem = 1;
	Insert->iItem = Index;
	Insert->pszText = (LPSTR)inPort;
	Insert->cchTextMax = (int)strlen(inPort);
  ConnectionList->SetItem(Insert);

	Insert->iSubItem = 2;
	Insert->iItem = Index;
	Insert->pszText = "Connecting";
	Insert->cchTextMax = (int)strlen("Connecting");
  ConnectionList->SetItem(Insert);

	Insert->iSubItem = 3;
	Insert->iItem = Index;
	Insert->pszText = "0";
	Insert->cchTextMax = (int)strlen("0");
  ConnectionList->SetItem(Insert);

	Insert->iSubItem = 4;
	Insert->iItem = Index;
	Insert->pszText = "0";
	Insert->cchTextMax = (int)strlen("0");
  ConnectionList->SetItem(Insert);


	delete Insert;
	return Index;
}

int CPhantomAgentDlg::AddConnection(CConnection* inConnection){
	if(inConnection){
		Connections.push_back(inConnection);
	}
	return 1;
}

int CPhantomAgentDlg::CleanConnections(bool bALL){
  list<CConnection*>::iterator itor;
	list<CConnection*>::iterator s;
	list<CConnection*>::iterator e;
	CConnection* aCon = 0;
	int ListIDRedux = 0;
	for(itor = Connections.begin(); itor != Connections.end(); itor++){
		if(!(*itor)){
			s = itor;
			e = ++itor;
			itor = Connections.erase(s, e);
			itor--;
      ListIDRedux++;
		}else{
			aCon = (*itor);
			if((aCon->m_RunState == CConnection::STATE_STOPPED) || bALL){
				ConnectionList->DeleteItem(aCon->m_ListID - ListIDRedux);
				ListIDRedux++;
				s = itor;
				e = ++itor;
				itor = Connections.erase(s, e);
				itor--;
				delete aCon;
			}else{
				aCon->m_ListID -= ListIDRedux;
			}
		}
	}
	return 1;
}

DWORD WINAPI ListenThreadFunction(void* Param){

	if(Param == NULL){
		return 0;
	}
	CPhantomAgentDlg* aDlg = (CPhantomAgentDlg*)Param;

  SSI_VERBOSE_LOG("BEGINNING LISTEN THREAD");
	//CString pcHost = "localhost";
	String sPort;
	int ListenPort = 4242;
	int MinPort = 5000;
	int MaxPort = 6000;

	aDlg->options.GetOption(String(OPT_LISTEN_PORT), sPort);
	if(sscanf(sPort.Str(), "%d", &ListenPort) != 1){
		aDlg->DispErrorBox("Bad LISTEN_PORT option, defaulting to 4242");
	}
	//aDlg->options.GetOption(String(OPT_MIN_AGENT_PORT), sPort);
	//if(sscanf(sPort.Str(), "%d", &MinPort) != 1){
	//	aDlg->DispErrorBox("Bad MIN_AGENT_PORT option, defaulting to 5000");
	//}
	//aDlg->options.GetOption(String(OPT_MAX_AGENT_PORT), sPort);
	//if(sscanf(sPort.Str(), "%d", &MaxPort) != 1){
	//	aDlg->DispErrorBox("Bad MAX_AGENT_PORT option, defaulting to 6000");
	//}

  CSocketManager aMgr;
	CSockCmd aCmd;
	//aMgr.Init(ListenPort, MinPort, MaxPort);
  aMgr.Init(ListenPort, MinPort, MaxPort);
  CSocketSSI* aSocket;
  while(aSocket = aMgr.GetConnection()){
		CConnection* aConnection = new CConnection(aDlg->bRegistered);
		aConnection->SetSocket(aSocket);
		aConnection->SetParent(aDlg);
    DWORD tID;

		String s;
		s.Format("%d", aSocket->myPort);
		aDlg->AddConnection(aConnection);
		aConnection->m_ListID = aDlg->AddConnection(aSocket->IPFromSocket(aSocket->myHandle), s.Str());
		HANDLE hListener = CreateThread(NULL, 0, ConnectionThreadFunction, (LPVOID)aConnection, 0, &tID);

		//ConnectionThreadFunction((LPVOID)aConnection);
		//CScript aClient(0, 0);
		//aClient.Load("C:\\PTDTesting\\scripts\\simple.txt");
		//aClient.Run(NORMAL_MODE);
		//Factory_ClearData();


		if(hListener){
		}else{
#ifdef _DEBUG
			MessageBox(NULL, "Could not create thread", "Error", MB_OK); // KEEP MSG
#endif
    	aConnection->m_ConnectionStatus = "** Error - Not Started";
		}
	}
  SSI_VERBOSE_LOG("ENDING LISTEN THREAD");
	return 0;
}

DWORD WINAPI ConnectionThreadFunction(void* Param){
	CConnection* aConnection = (CConnection*)Param;
	if(aConnection == NULL){
		return 0;
	}
  SSI_VERBOSE_LOG("BEGINNING CONNECTION THREAD");
	aConnection->Run();
  SSI_VERBOSE_LOG("ENDING CONNECTION THREAD");
	return 1;
}

void CPhantomAgentDlg::OnTimer(UINT nIDEvent)
{
	// TODO: Add your message handler code here and/or call default
	CleanConnections(false);
	UpdateDataDisplay();

  if(m_FirstTimer){
    m_FirstTimer = FALSE;
    String HideOption;
    options.GetOption(OPT_HIDE_AGENT, HideOption);
    if(HideOption == "1"){
      OnPopupHide();
    }else{
      OnPopupShow();
    }
  }

	CDialog::OnTimer(nIDEvent);

}

void CPhantomAgentDlg::ValidateOptions(void)
{
	if(!options.HasKey(String(OPT_LISTEN_PORT))){
		options.AddOption(String(OPT_LISTEN_PORT), "4242");
	}
  //if(!options.HasKey(String(OPT_MIN_AGENT_PORT))){
	//	options.AddOption(String(OPT_MIN_AGENT_PORT), "5000");
	//}
  //if(!options.HasKey(String(OPT_MAX_AGENT_PORT))){
	//	options.AddOption(String(OPT_MAX_AGENT_PORT), "6000");
	//}
	//if(!options.HasKey(String(OPT_MAX_CONNECTIONS))){
	//	options.AddOption(String(OPT_MAX_CONNECTIONS), "10");
	//}
	//if(!options.HasKey(String(OPT_USE_SSL))){
	//	options.AddOption(String(OPT_USE_SSL), "0");
	//}
	//if(!options.HasKey(String(OPT_SSL_KEY))){
	//	options.AddOption(String(OPT_SSL_KEY), "");
	//}
	if(!options.HasKey(String(OPT_HIDE_AGENT))){
		options.AddOption(String(OPT_HIDE_AGENT), "0");
	}
	if(!options.HasKey(String(OPT_SAVE_LOG))){
		options.AddOption(String(OPT_SAVE_LOG), "0");
	}
	if(!options.HasKey(String(OPT_SAVE_LOG_FILE))){
		options.AddOption(String(OPT_SAVE_LOG_FILE), "");
	}

	bRegistered = TRUE;
	/*
  if(options.HasKey(String(OPT_REG_KEY))){
    String sVal;
    if(options.GetOption(String(OPT_REG_KEY), sVal)){
      CReg aReg;
      char Buff[1024];  // Have to use Buff because CReg::CheckKey alters contents
      sprintf(Buff, "%s", sVal.Str());
      if(aReg.CheckKey(300, Buff)){
        bRegistered = TRUE;
      }
    }
  }

  if(bRegistered == FALSE){
    CRegistrationSplashDlg aDlg;
    if(aDlg.DoModal() == IDOK){
      if(!options.HasKey(String(OPT_REG_KEY))){
        options.AddOption(String(OPT_REG_KEY),String((LPCTSTR) aDlg.sRegKey));
      }else{
        options.SetOption(String(OPT_REG_KEY),String((LPCTSTR) aDlg.sRegKey));
      }
      options.SaveToFile(OPTIONS_FILE);
      bRegistered = TRUE;
    }
  }
  */

}

void CPhantomAgentDlg::DispErrorBox(const char* sMess)
{
	if(sMess == 0) return;
	MessageBox(sMess, ERR_TITLE, MB_OK);
}

void CPhantomAgentDlg::UpdateDataDisplay(void)
{
	String sTemp = "";
	String sOpt;
	options.GetOption(OPT_LISTEN_PORT, sOpt);
	sTemp = sTemp + sOpt;
	SetDlgItemText(IDC_LISTENING_PORT, sTemp.Str());
	sTemp.Format("%d", Connections.size());
	SetDlgItemText(IDC_CONNECTIONS, sTemp.Str());
	UpdateConnections();
}

void CPhantomAgentDlg::UpdateConnections(void)
{
	list<CConnection*>::iterator itor;
	CConnection* aCon = 0;
	LVITEM Insert;
	String s;

	for(itor = Connections.begin(); itor != Connections.end(); itor++){
		if(!(*itor)){
		}else{
			aCon = (*itor);

			Insert.mask = LVIF_TEXT;

			Insert.iItem = aCon->m_ListID;
			Insert.iSubItem = 2;
      Insert.pszText = (LPSTR)aCon->m_ConnectionStatus.Str();
			Insert.cchTextMax = aCon->m_ConnectionStatus.GetLength();
			ConnectionList->SetItem(&Insert);

			m_SentCnt = m_SentCnt + aCon->getSentCtr();
			s.Format("%d", aCon->getSentCtr());
			Insert.iItem = aCon->m_ListID;
			Insert.iSubItem = 3;
			Insert.pszText = (LPSTR)s.Str();
			Insert.cchTextMax = s.GetLength();
			ConnectionList->SetItem(&Insert);

			m_RecvCnt = m_RecvCnt + aCon->getRecvCtr();
			s.Format("%d", aCon->getRecvCtr());
			Insert.iItem = aCon->m_ListID;
			Insert.iSubItem = 4;
			Insert.pszText = (LPSTR)s.Str();
			Insert.cchTextMax = s.GetLength();
			ConnectionList->SetItem(&Insert);

			Insert.iItem = aCon->m_ListID;
			Insert.iSubItem = 5;
      Insert.pszText = (LPSTR)aCon->m_ConnectionInfo.Str();
			Insert.cchTextMax = aCon->m_ConnectionStatus.GetLength();
			ConnectionList->SetItem(&Insert);


			//if(aCon->m_RunState == CConnection::STATE_STOPPED){
			//	ConnectionList->DeleteItem(aCon->m_ListID);
			//	s = itor;
			//	e = ++itor;
			//	itor = Connections.erase(s, e);
			//	itor--;
			//	delete aCon;
			//}
		}
	}

	//s.Format("%d", m_SentCnt);
	//SetDlgItemText(IDC_TOTAL_SENT, s.Str());
	//s.Format("%d", m_RecvCnt);
	//SetDlgItemText(IDC_TOTAL_RECEIVED, s.Str());
}

void CPhantomAgentDlg::InitControls(void)
{
	ConnectionList = (CListCtrl*)GetDlgItem(IDC_CONNECTION_LIST);
	ConnectionList->InsertColumn(ID_HOST_ID, ID_HOST_TITLE, LVCFMT_LEFT, 75, ID_HOST_ID);
	ConnectionList->InsertColumn(ID_PORT_ID, ID_PORT_TITLE, LVCFMT_LEFT, 60, ID_PORT_ID);
	ConnectionList->InsertColumn(ID_STAT_ID, ID_STAT_TITLE, LVCFMT_LEFT, 75, ID_STAT_ID);
	ConnectionList->InsertColumn(ID_SENT_ID, ID_SENT_TITLE, LVCFMT_LEFT, 60, ID_SENT_ID);
	ConnectionList->InsertColumn(ID_RECV_ID, ID_RECV_TITLE, LVCFMT_LEFT, 60, ID_RECV_ID);
  ConnectionList->InsertColumn(ID_INFO_ID, ID_INFO_TITLE, LVCFMT_LEFT, 300, ID_INFO_ID);

	/// TOOL BAR /////
	BYTE tbStyle = TBSTYLE_BUTTON;
	TBBUTTON aButton;
	aButton.fsState = TBSTATE_ENABLED;
	aButton.fsStyle = tbStyle;

	RECT Rect;
	Rect.left = 0;
	Rect.right = 300;
	Rect.top = 0;
	Rect.bottom = 0;

	m_ToolBar.Create(TBSTYLE_FLAT | WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS, Rect, this, IDC_TOOLBAR);	
	m_ToolBar.AddBitmap(2, IDR_MAIN_TOOLBAR);
	
	aButton.iBitmap = 0;
	aButton.iString = NULL;
	aButton.idCommand = ID_VIEW_HIDE;
	m_ToolBar.AddButtons(1, &aButton);

	aButton.iBitmap = 1;
	aButton.iString = NULL;
	aButton.idCommand = ID_VIEW_OPTIONS;
	m_ToolBar.AddButtons(1, &aButton);
}

void CPhantomAgentDlg::OnViewOptions()
{
	COptionsDlg* aDlg = new COptionsDlg(this);
	aDlg->DoModal();
	delete aDlg;
	
	// TODO: Add your command handler code here
}

void CPhantomAgentDlg::OnViewHide()
{
	OnPopupHide();
	// TODO: Add your command handler code here
}

void CPhantomAgentDlg::OnViewExit()
{
	CDialog::OnOK();
	// TODO: Add your command handler code here
}

BOOL CPhantomAgentDlg::SetIconic(void)
{
	NOTIFYICONDATA iData;
	char Duh[64] = "Phantom Agent";
	iData.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
	iData.hWnd = this->m_hWnd;
	//iData.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_TRAYICON));
  iData.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON2));
	iData.uID = 10;
	iData.uCallbackMessage = TRAY_CALLBACK;
	strncpy(iData.szTip, Duh, sizeof(iData.szTip));
	iData.cbSize = sizeof(iData);
	return Shell_NotifyIcon(NIM_ADD, &iData);

}

BOOL CPhantomAgentDlg::RemoveIconic()
{
	NOTIFYICONDATA iData;
	iData.uFlags = NIF_ICON;
	iData.uID = 10;
	iData.hWnd = this->m_hWnd;	
	iData.hIcon = GetIcon(TRUE);;
	iData.cbSize = sizeof(iData);
	return Shell_NotifyIcon(NIM_DELETE, &iData);	
}


BOOL CPhantomAgentDlg::DestroyWindow()
{
	// TODO: Add your specialized code here and/or call the base class
	CleanConnections(true);
  RemoveIconic();
	return CDialog::DestroyWindow();
}

LRESULT CPhantomAgentDlg::OnTrayNotify(WPARAM uID, LPARAM lEvent)
{
	POINT bPoint;
	GetCursorPos(&bPoint);

	if((UINT)lEvent == WM_RBUTTONUP)
	{
		CMenu Menu;
		Menu.CreatePopupMenu();
		Menu.InsertMenu(-1, MF_BYPOSITION | MF_STRING, ID_TRAY_VIEW, "&View");
		Menu.InsertMenu(-1, MF_BYPOSITION | MF_STRING, ID_VIEW_EXIT, "&Exit");
		Menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_LEFTBUTTON, bPoint.x, bPoint.y, this);
		Menu.DestroyMenu();	
	}
	if((UINT)lEvent == WM_LBUTTONDBLCLK)
	{
		if(m_HiddenFlg)
		{
			OnPopupShow();		
		}
		else
		{
			OnPopupHide();		
		}
	}
	return 0;
}

void CPhantomAgentDlg::OnPopupShow()
{
	ShowWindow(SW_SHOW);
	ShowWindow(SW_RESTORE);

	SetForegroundWindow();
	BringWindowToTop();
	SetActiveWindow();
	SetFocus();

	m_HiddenFlg = FALSE;
}

void CPhantomAgentDlg::OnPopupHide()
{
	ShowWindow(SW_MINIMIZE);
	ShowWindow(SW_HIDE);
	m_HiddenFlg = TRUE;
}

void CPhantomAgentDlg::InitLogFile(void)
{
  String sVal;
  
  if(options.GetOption(OPT_SAVE_LOG, sVal)){
		if(sVal == "1"){
   
			if(options.GetOption(OPT_SAVE_LOG_FILE, sVal)){
        int iLen = sVal.GetLength();
        if((iLen <= 0) || (iLen > 1023)){
          DispErrorBox("Log file path must be less than 1023 characters");
        }else{
          CSocketSSI::SetLogFile(sVal.Str());
        }
	    }
		}
	}


}
